package uk.ac.sanger.dasregistry.timer;

import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;

import javax.servlet.ServletException;
import javax.sql.DataSource;

import java.util.logging.Logger;
import org.biojava.dasobert.dasregistry.DasCoordinateSystem;
import org.biojava.dasobert.dasregistry.DasSource;
import org.biojava.services.das.dao.DasSourceManager;
import org.biojava.services.das.registry.ConfigBean;
import org.biojava.services.das.registry.DasRegistrySql;
import org.biojava.services.das.registry.RegistryDirectoryInfo;
import org.biojava.services.das.servlets.ServletResponseIndexWriter;
import org.biojava.services.das2.Das1SourceDbProvider;
import org.quartz.Job;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import dasregistry.utils.MachineInfo;

public class LuceneIndexer {
	private static final long serialVersionUID = 1L;

	public static Logger logger = Logger
			.getLogger("uk.ac.sanger.dasregistry.timer.LuceneIndexer");

	int contactParentFrequency;
	Timer timer;
	DasSourceManager dasSourceManager;
	
	public DasSourceManager getDasSourceManager() {
		return dasSourceManager;
	}

	public void setDasSourceManager(DasSourceManager dasSourceManager) {
		this.dasSourceManager = dasSourceManager;
	}

	boolean showValidationLog = true;
	public static final int ONEHOUR = 1000 * 60 * 60;
	DasRegistrySql registry;

	private String directoryForFiles=".";//default is current dir

	// public static final int ONEHOUR = 1000 * 60 ;

	public DasRegistrySql getRegistry() {
		return registry;
	}

	public void setRegistry(DasRegistrySql registry) {
		this.registry = registry;
	}

	/**
	 * run indexing on all registry info to produce xml files for Sanger indexer
	 * @param ignoreAdminChecks TODO
	 * @return succesful or not
	 */

	public boolean indexAll(boolean ignoreAdminChecks){
		
		// String computerToRunIndexOn =
		// getInitParameter("computerToRunIndexOn");
		// System.out.println("computer to run index on=" +
		// computerToRunIndexOn);
		
		
		//MachineInfo machine=new MachineInfo();
		
			// put some code to test if a specific computer name - then index if
			// not don't do any of the tests
			// if the correct machine then the files can then be picked up by
			// the getDasregistryIndexes.sh script that is run by a cron

			Connection conn = null;
			boolean doIndexing = false;
			try {

				DataSource dataSource = registry.getDataSource();
				conn = dataSource.getConnection();

				doIndexing = dasSourceManager.doAdminChecks(conn, "lastIndex",
						"indexingStarted", "indexing");
				

			} catch (Exception e) {
				e.printStackTrace();
				return false;
			} finally {
				if (conn != null) {
					try {
						conn.close();
					} catch (SQLException e) {
						e.printStackTrace();
					}
				}
			}

			if(ignoreAdminChecks){
				doIndexing=true;
			}
			if (!doIndexing) {
				logger
						.info(" not running indexing due to dao admin checks... ");
				return false;
			}

			logger.info("running auto indexing ...");
			// String directory = getServletContext().getRealPath("/");

			// System.out.println("dir=" + directory);
			//RegistryDirectoryInfo info=RegistryDirectoryInfo.getRegistryDirectoryInfo();
			//File dir=new File("dummyFile.txt");
			//String filePath=dir.getAbsolutePath();
			try {
				//currently the index needs a request to Das2ResgistryServlet to have run for the directory to be set - there should be a simpler way than this
				///e.g. geting root to allow write permissions outside webapps for the tomcat user
				index(directoryForFiles);
			} catch (ServletException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return false;
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return false;
			}
			releaseIndexingLock(registry);

			registry = null;
			return true;

	}

	private void releaseIndexingLock(DasRegistrySql registry) {
		System.out.println("releasing indexing lock");
		DataSource dataSource = registry.getDataSource();

		Connection conn = null;
		// boolean doValidate = false;
		try {
			conn = dataSource.getConnection();
			dasSourceManager.releaseAdminLock(conn, "indexing", "lastIndex");
			// as we now update the valid_capabilities tables we want
			// to tell the sources.xml returned by the registry it will need
			// updating etc
			// dao.pingLastModified(conn);

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
	}

	private void index(String directory) throws ServletException, IOException {
		List<DasSource> sources = registry.listServices();
		Map<String, List<Map<String, String>>> types = this.getAutoIdWithTypes(sources);

		ServletResponseIndexWriter writer = new ServletResponseIndexWriter(
				directory);
		List<DasCoordinateSystem> allCoordinates=null;
		try {
			allCoordinates=registry.getAllCoordinateSystems();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		writer.writeIndexResponse(sources, types, allCoordinates);

	}
	
	/**
	 * get a map of source url to types info
	 * @return map of unique url to types info for each source in the registry
	 */
	public Map<String, List<Map<String,String>>> getAutoIdWithTypes(List<DasSource> sources){
		Map<String, List<Map<String,String>>> map=new HashMap<String, List<Map<String,String>>>();
		for(DasSource source:sources){
		int auto_id=registry.getAutoID4DasSource(source);
		List<Map<String, String>> types=registry.getTypes(String.valueOf(auto_id));
		map.put(source.getId(), types);
		}
		
		return map;
		
		
	}

	public void setDirectory(String directory) {
		// TODO Auto-generated method stub
		this.directoryForFiles=directory;
	}
	

}
